﻿//#define NEWLAT

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Markup;

using agree.configuration;

using alib;
using alib.Lattice;
using alib.Character;
using alib.Collections;
using alib.Debugging;
using alib.Enumerable;
using alib.Hashing;
using alib.dg;

namespace agree
{
	[DebuggerDisplay("{ToString(),nq}")]
	public abstract class AgreeTrellis<T> :
#if !NEWLAT
 Trellis<T>,//, IIdentList<T>
#else
		newlat<T>,
#endif
		IIdentity
		where T : class, ITfsSlot
	{
		public AgreeTrellis(IIdentity prv)
		{
			this.prv = prv;
		}

#if false
		public T this[int index]
		{
			get
			{
				int i = 0;
				var e = base.Edges.GetEnumerator();
				do
					if (!e.MoveNext())
						throw new Exception();
				while (i++ < index);
				return e.Current.data;
			}
		}

		public int Count { get { return base.EdgeCount; } }

		public IEnumerator<T> GetEnumerator() { return base.Edges.Select(e => e.data).GetEnumerator(); }

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }

		void System.Collections.ICollection.CopyTo(Array array, int index)
		{
			var e = base.Edges.GetEnumerator();
			while (e.MoveNext())
				array.SetValue(e.Current.data, index++);
		}

		bool System.Collections.ICollection.IsSynchronized { get { return false; } }

		Object System.Collections.ICollection.SyncRoot { get { return this; } }
#endif

#if DEBUG && !NEWLAT
		[DebuggerDisplay("count:{_10_vertexes_dbg.Length}", Name = "VERTICIES")]
		_alat_vertext_dbg[] _10_vertexes_dbg
		{
			get
			{
				_alat_vertext_dbg[] arr = new _alat_vertext_dbg[VertexCount];
				int i = 0;
				foreach (var v in base.Vertices)
					arr[i++] = new _alat_vertext_dbg(v);
				Array.Sort(arr);
				return arr;
			}
		}


		[DebuggerDisplay("count:{_20_edges_dbg.Length}", Name = "EDGES")]
		_alat_edge_dbg[] _20_edges_dbg
		{
			get
			{
				_alat_edge_dbg[] arr = new _alat_edge_dbg[EdgeCount];
				int i = 0;
				foreach (var e in base.Edges)
					arr[i++] = new _alat_edge_dbg(e);
				return arr;
			}
		}

		[DebuggerDisplay("", Name = "All tokens")]
		T[] _30_tokens_debug
		{
			get { return Edges.Select(e => e.data).ToArray(); }
		}

		public class _alat_dbg_type_proxy
		{
			public _alat_dbg_type_proxy(TokenMappingLattice lat)
			{
				this.lat = lat;
			}
			TokenMappingLattice lat;
		};

		[DebuggerDisplay("{vert.LongDisplay(),nq}")]
		public class _alat_vertext_dbg : IComparable<_alat_vertext_dbg>
		{
			public _alat_vertext_dbg(LatticeVertex vert)
			{
				this.vert = vert;
			}
			[DebuggerBrowsable(DebuggerBrowsableState.Never)]
			AgreeTrellis<T> latt { get { return (AgreeTrellis<T>)vert.lat; } }

			[DebuggerBrowsable(DebuggerBrowsableState.Never)]
			readonly LatticeVertex vert;

#if false
			[DebuggerDisplay("    {lefts.Length} inbound edges from leftwards")]
			public _alat_edge_dbg[] lefts { get { return vert.lefts.Select(e => new _alat_edge_dbg(e)).ToArray(); } }

			[DebuggerDisplay("    {rights.Length} outbound edges going rightwards")]
			public _alat_edge_dbg[] rights { get { return vert.rights.Select(e => new _alat_edge_dbg(e)).ToArray(); } }
#endif

			public override string ToString() { return vert.StringId; }

			public int CompareTo(_alat_vertext_dbg other) { return vert.CompareTo(other.vert); }
		}

		[DebuggerDisplay("{edge.LongDisplay(),nq}")]
		public class _alat_edge_dbg : IComparable<_alat_edge_dbg>
		{
			public _alat_edge_dbg(LatticeEdge edge)
			{
				this.edge = edge;
			}
			[DebuggerBrowsable(DebuggerBrowsableState.Never)]
			AgreeTrellis<T> latt { get { return (AgreeTrellis<T>)edge.lat; } }

			[DebuggerBrowsable(DebuggerBrowsableState.Never)]
			readonly LatticeEdge edge;

#if false
			_alat_vertext_dbg source { get { return new _alat_vertext_dbg(edge.Source); } }
			_alat_vertext_dbg target { get { return new _alat_vertext_dbg(edge.Target); } }
			T token { get { return edge.data; } }
			ITfsSlot TfsSlot { get { return edge.data; } }

			[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
			TfsSlot[] _BELOW { get { return SlotRefArray.GetConstraints(edge.data); } }
#endif

			public override String ToString() { return edge.StringId; }

			public int CompareTo(_alat_edge_dbg other) { return edge.CompareTo(other.edge); }
		}

		public override String ToString()
		{
			return String.Format("{0} verticies: {1}  edges: {2}", this.GetType().Name, VertexCount, EdgeCount);
		}
#endif

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public IIdentity prv;
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public IIdentity Trace { get { return prv; } }
	};
}
